package linter.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.gson.Gson;
import com.qiniu.http.Response;
import com.qiniu.storage.Configuration;
import com.qiniu.storage.Region;
import com.qiniu.storage.UploadManager;
import com.qiniu.storage.model.DefaultPutRet;
import com.qiniu.util.Auth;
import linter.POJO.DO.ClassNoteclassRelation;
import linter.POJO.DO.CollectNoteRelation;
import linter.POJO.DO.Note;
import linter.POJO.DO.UserNoteclassRelation;
import linter.POJO.DTO.NoteDTO;
import linter.mapper.ClassNoteclassRelationMapper;
import linter.mapper.CollectNoteRelationMapper;
import linter.mapper.NoteMapper;
import linter.mapper.UserNoteclassRelationMapper;
import linter.service.NoteService;
import linter.utils.PropertyUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import static linter.custom.Constant.*;
import static linter.custom.CustomResultType.*;
import static linter.utils.ModelUtils.generateUUID;

/**
* @author 北煜
* @description 针对表【note】的数据库操作Service实现
* @createDate 2023-07-25 09:30:43
*/
@Service
public class NoteServiceImpl extends ServiceImpl<NoteMapper, Note>
    implements NoteService{

    @Resource
    NoteMapper noteMapper;
    @Resource
    CollectNoteRelationMapper collectNoteRelationMapper;
    @Resource
    UserNoteclassRelationMapper userNoteclassRelationMapper;
    @Resource
    ClassNoteclassRelationMapper classNoteclassRelationMapper;

    // TODO：封面和标题
    @Override
    public Object setNoteForJson(Long uuid, String noteJson, String noteTitle) {
        Note note = new Note();
        Date date = new Date();
        note.setNotetitle(noteTitle);
        note.setNoteimg(DEFAULT_IMG_URL_NOTE);
        note.setNotejson(noteJson);
        note.setUuid(uuid);
        note.setViews(NOTE_CONSTANT_INITIAL_VALUE_DEFAULT);
        note.setLikesNub(NOTE_CONSTANT_INITIAL_VALUE_DEFAULT);
        note.setCollectNub(NOTE_CONSTANT_INITIAL_VALUE_DEFAULT);
        note.setCreateTime(date);
        note.setUpdateTime(date);
        int flag = noteMapper.insert(PropertyUtils.doToDto(note, Note.class));
        return flag != 1? CREATION_ERROR : CREATION_SUCCESS;
    }

    // TODO：类型可能有点问题
    @Override
    public Object getNoteByUuid(Long uuid,Long noteId) { return noteMapper.getNote(uuid, noteId); }

    @Override
    public PageInfo<NoteDTO> getAllNote(int pageSize, int pageNum, Long uuid) {
        return PageHelper.startPage(pageNum, pageSize).doSelectPageInfo(() -> noteMapper.selectNoteByUuid(uuid));
    }

    @Override
    public String updateNoteJsonByUser(Long uuid, Long noteId, String noteJson, String noteTitle) {
        if(noteMapper.updataNoteJsonByUser(uuid, noteId, noteJson, noteTitle)){ return UPDATE_SUCCESS; }
        return UPDATE_ERROR;
    }


    @Override
    public PageInfo<Object> setNoteImgAndNoteTitleByUuid(Long uuid, Integer pageNum, Integer pageSize) {
        return PageHelper.startPage(pageNum, pageSize).doSelectPageInfo(()->noteMapper.selectNoteImgAndNoteTitleByUuid(uuid));
    }

    @Override
    public PageInfo<Note> getRecentFiles(Long uuid, int pageSize, int pageNum) {
        PageHelper.startPage(1, 5);
        List<Note> list = noteMapper.selectRecentFiles(uuid);
        return new PageInfo<>(list);
    }

    @Override
    public String deleteNoteByNoteId(Long noteId, Long uuid) {
        if (noteMapper.updateByNoteId(noteId, uuid)){ return DELETE_SUCCESS; }
        return DELETE_ERROR;
    }

    // TODO: 逻辑设计有问题，应该当用户查看过笔记后进行记录笔记ID
    @Override
    public PageInfo<NoteDTO> getViewsNote(Long uuid, int pageSize, int pageNum) {
        PageHelper.startPage(1, 5);
        List<NoteDTO> list = noteMapper.selectViewsNote(uuid);
        return new PageInfo<>(list);
    }

    @Override
    public String createNoteNull(Long uuid, MultipartFile file, String noteName) {
        Date date = new Date();
        Note note = new Note();
        // 构造一个带指定Region对象的配置类
        Configuration cfg = new Configuration(Region.region2());
        cfg.resumableUploadAPIVersion = Configuration.ResumableUploadAPIVersion.V2;
        UploadManager uploadManager = new UploadManager(cfg);
        Auth auth = Auth.create(ACCESS_KEY_QINIU, SECRET_KEY_QINIU);
        String bucketName = BUCKET_NAME_QINIU;
        String key = "User/Notes/Images"+ "/" + noteName + generateUUID() + uuid;
        String baseUrl = "http://qiniuyun.linter.top";
        String url = baseUrl + "/" + key;
        byte[] fileContent = new byte[0];
        try {
            fileContent = file.getBytes();
            try(ByteArrayInputStream inputStream = new ByteArrayInputStream(fileContent)){
                String upToken = auth.uploadToken(bucketName);
                Response response = uploadManager.put(inputStream, key, upToken, null, null);
                DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);

                note.setNotetitle(noteName);
                note.setUuid(uuid);
                note.setNoteimg(url);
                note.setViews(NOTE_CONSTANT_INITIAL_VALUE_DEFAULT);
                note.setLikesNub(NOTE_CONSTANT_INITIAL_VALUE_DEFAULT);
                note.setCollectNub(NOTE_CONSTANT_INITIAL_VALUE_DEFAULT);
                note.setCreateTime(date);
                note.setUpdateTime(date);
                note.setNotejson(null);
                int flag = noteMapper.insert(PropertyUtils.doToDto(note, Note.class));

                if (response.statusCode == RES_SUCCESS) {
                    return putRet.hash + ": " + UPLOAD_SUCCESS;
                } else {
                    throw new RuntimeException(UPLOAD_ERROR + ": " + response.bodyString());
                }
            }catch (IOException e) {
                throw new RuntimeException(e);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public PageInfo<NoteDTO> selNotCollectNote(Long uuid) {
        QueryWrapper<Note> queryWrapper = new QueryWrapper<>();
        // 得到这个用户的所有笔记
        List<Note> noteList = noteMapper.selectList(queryWrapper.select("*").eq("uuid", uuid));
        List<Long> collectNoteRelationList = noteList.stream().map(Note :: getId).collect(Collectors.toList());
        // 得到这个用户收藏的所有笔记
        QueryWrapper<CollectNoteRelation> collectNoteRelationQueryWrapper = new QueryWrapper<>();
        List<CollectNoteRelation> CNRList = collectNoteRelationMapper.selectList(collectNoteRelationQueryWrapper
                .in("note_id", collectNoteRelationList));
        CNRList = CNRList.stream()
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
        List<Long> collectNote = CNRList.stream()
                .map(CollectNoteRelation::getNoteId)
                .collect(Collectors.toList());
        // 得到这个用户没有收藏的所有笔记
        List<Long> uncollectedNoteIds = collectNoteRelationList.stream()
                .filter(id -> !collectNote.contains(id))
                .distinct()
                .collect(Collectors.toList());
        List<Note> list = new ArrayList<>();
        for (Long id : uncollectedNoteIds) {
            Note note = noteMapper.selectById(id);
            if (note != null){ list.add(note); }
        }
        return new PageInfo<>(PropertyUtils.listToList(list, NoteDTO.class));
    }

    @Override
    public PageInfo<NoteDTO> getNoteClassByUuid(Long uuid) {
        PageHelper.startPage(1, 10);
        QueryWrapper<UserNoteclassRelation> userNoteclassRelationQueryWrapper = new QueryWrapper<>();
        List<UserNoteclassRelation> userNoteclassRelation = userNoteclassRelationMapper
                .selectList(userNoteclassRelationQueryWrapper.eq("uuid", uuid));
        List<Integer> CNRId = userNoteclassRelation.stream()
                .map(UserNoteclassRelation::getCnrelationId)
                .collect(Collectors.toList());
        List<ClassNoteclassRelation> classNoteclassRelationList = new ArrayList<>();
        for (Integer id : CNRId){
            ClassNoteclassRelation classNoteclassRelation = classNoteclassRelationMapper.selectById(id);
            if (classNoteclassRelation != null){ classNoteclassRelationList.add(classNoteclassRelation); }
        }
        List<Long> noteId = classNoteclassRelationList.stream()
                .map(ClassNoteclassRelation::getNoteId)
                .collect(Collectors.toList());
        List<Note> noteList = new ArrayList<>();
        for (Long id : noteId){
            Note note = noteMapper.selectById(id);
            if (note != null){ noteList.add(note); }
        }
        return new PageInfo<>(PropertyUtils.listToList(noteList, NoteDTO.class));
    }

    @Override
    public PageInfo<NoteDTO> selNoteClass(Long uuid, String noteTitle) {
        PageHelper.startPage(1, 10);
        QueryWrapper<Note> noteQueryWrapper = new QueryWrapper<>();
        List<Note> noteList = noteMapper.selectList(noteQueryWrapper
                .eq("uuid",29)
                .like("noteTitle","%"+noteTitle+"%"));
        return new PageInfo<>(PropertyUtils.listToList(noteList, NoteDTO.class));
    }

    @Override
    public NoteDTO getNoteByNoteId(Integer noteId) {
        QueryWrapper<Note> queryWrapper = new QueryWrapper<>();
        return PropertyUtils
                .doToDto(noteMapper.selectOne(queryWrapper.eq("id",noteId).eq("is_delete",0))
                        ,NoteDTO.class);
    }


}




